home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 1999 #2 / Amiga Plus CD - 1999 - No. 2.iso / System-Boost / Workbench / Archive / PPCunlzx / unlzx.c < prev    next >
C/C++ Source or Header  |  1998-06-18  |  36KB  |  1,356 lines

  1. /* $VER: unlzx.c 1.0 (22.2.98) */
  2. /* Created: 11.2.98 */
  3.  
  4. /* LZX Extract in (supposedly) portable C.                                */
  5.  
  6. /* Compile with:                                                          */
  7. /* gcc unlzx.c -ounlzx -O2                                                */
  8.  
  9. /* Thanks to Dan Fraser for decoding the coredumps and helping me track   */
  10. /* down some HIDEOUSLY ANNOYING bugs.                                     */
  11.  
  12. /* Everything is accessed as unsigned char's to try and avoid problems    */
  13. /* with byte order and alignment. Most of the decrunch functions          */
  14. /* encourage overruns in the buffers to make things as fast as possible.  */
  15. /* All the time is taken up in crc_calc() and decrunch() so they are      */
  16. /* pretty damn optimized. Don't try to understand this program.           */
  17.  
  18. /* ---------------------------------------------------------------------- */
  19.  
  20. #include <stdlib.h>
  21. #include <stdio.h>
  22.  
  23. /* ---------------------------------------------------------------------- */
  24.  
  25. static const unsigned char VERSION[]="$VER: unlzx 1.0 (22.2.98)";
  26.  
  27. /* ---------------------------------------------------------------------- */
  28.  
  29. int mode;
  30.  
  31. unsigned char info_header[10];
  32. unsigned char archive_header[31];
  33. unsigned char header_filename[256];
  34. unsigned char header_comment[256];
  35.  
  36. unsigned int pack_size;
  37. unsigned int unpack_size;
  38.  
  39. unsigned int crc;
  40. unsigned int year, month, day;
  41. unsigned int hour, minute, second;
  42. unsigned char attributes;
  43. unsigned char pack_mode;
  44.  
  45. /* ---------------------------------------------------------------------- */
  46.  
  47. struct filename_node
  48. {
  49.  struct filename_node *next;
  50.  unsigned int length;
  51.  unsigned int crc;
  52.  char filename[256];
  53. };
  54.  
  55. struct filename_node *filename_list;
  56.  
  57. /* ---------------------------------------------------------------------- */
  58.  
  59. unsigned char read_buffer[16384]; /* have a reasonable sized read buffer */
  60. unsigned char decrunch_buffer[258+65536+258]; /* allow overrun for speed */
  61.  
  62. unsigned char *source;
  63. unsigned char *destination;
  64. unsigned char *source_end;
  65. unsigned char *destination_end;
  66.  
  67. unsigned int decrunch_method;
  68. unsigned int decrunch_length;
  69. unsigned int last_offset;
  70. unsigned int global_control;
  71. int global_shift;
  72.  
  73. unsigned char offset_len[8];
  74. unsigned short offset_table[128];
  75. unsigned char huffman20_len[20];
  76. unsigned short huffman20_table[96];
  77. unsigned char literal_len[768];
  78. unsigned short literal_table[5120];
  79.  
  80. /* ---------------------------------------------------------------------- */
  81.  
  82. static const char *month_str[16]=
  83. {
  84.  "jan", "feb", "mar", "apr", "may", "jun", "jul", "aug",
  85.  "sep", "oct", "nov", "dec", "?13", "?14", "?15", "?16"
  86. };
  87.  
  88. /* ---------------------------------------------------------------------- */
  89.  
  90. unsigned int sum;
  91.  
  92. static const unsigned int crc_table[256]=
  93. {
  94.  0x00000000,0x77073096,0xEE0E612C,0x990951BA,0x076DC419,0x706AF48F,
  95.  0xE963A535,0x9E6495A3,0x0EDB8832,0x79DCB8A4,0xE0D5E91E,0x97D2D988,
  96.  0x09B64C2B,0x7EB17CBD,0xE7B82D07,0x90BF1D91,0x1DB71064,0x6AB020F2,
  97.  0xF3B97148,0x84BE41DE,0x1ADAD47D,0x6DDDE4EB,0xF4D4B551,0x83D385C7,
  98.  0x136C9856,0x646BA8C0,0xFD62F97A,0x8A65C9EC,0x14015C4F,0x63066CD9,
  99.  0xFA0F3D63,0x8D080DF5,0x3B6E20C8,0x4C69105E,0xD56041E4,0xA2677172,
  100.  0x3C03E4D1,0x4B04D447,0xD20D85FD,0xA50AB56B,0x35B5A8FA,0x42B2986C,
  101.  0xDBBBC9D6,0xACBCF940,0x32D86CE3,0x45DF5C75,0xDCD60DCF,0xABD13D59,
  102.  0x26D930AC,0x51DE003A,0xC8D75180,0xBFD06116,0x21B4F4B5,0x56B3C423,
  103.  0xCFBA9599,0xB8BDA50F,0x2802B89E,0x5F058808,0xC60CD9B2,0xB10BE924,
  104.  0x2F6F7C87,0x58684C11,0xC1611DAB,0xB6662D3D,0x76DC4190,0x01DB7106,
  105.  0x98D220BC,0xEFD5102A,0x71B18589,0x06B6B51F,0x9FBFE4A5,0xE8B8D433,
  106.  0x7807C9A2,0x0F00F934,0x9609A88E,0xE10E9818,0x7F6A0DBB,0x086D3D2D,
  107.  0x91646C97,0xE6635C01,0x6B6B51F4,0x1C6C6162,0x856530D8,0xF262004E,
  108.  0x6C0695ED,0x1B01A57B,0x8208F4C1,0xF50FC457,0x65B0D9C6,0x12B7E950,
  109.  0x8BBEB8EA,0xFCB9887C,0x62DD1DDF,0x15DA2D49,0x8CD37CF3,0xFBD44C65,
  110.  0x4DB26158,0x3AB551CE,0xA3BC0074,0xD4BB30E2,0x4ADFA541,0x3DD895D7,
  111.  0xA4D1C46D,0xD3D6F4FB,0x4369E96A,0x346ED9FC,0xAD678846,0xDA60B8D0,
  112.  0x44042D73,0x33031DE5,0xAA0A4C5F,0xDD0D7CC9,0x5005713C,0x270241AA,
  113.  0xBE0B1010,0xC90C2086,0x5768B525,0x206F85B3,0xB966D409,0xCE61E49F,
  114.  0x5EDEF90E,0x29D9C998,0xB0D09822,0xC7D7A8B4,0x59B33D17,0x2EB40D81,
  115.  0xB7BD5C3B,0xC0BA6CAD,0xEDB88320,0x9ABFB3B6,0x03B6E20C,0x74B1D29A,
  116.  0xEAD54739,0x9DD277AF,0x04DB2615,0x73DC1683,0xE3630B12,0x94643B84,
  117.  0x0D6D6A3E,0x7A6A5AA8,0xE40ECF0B,0x9309FF9D,0x0A00AE27,0x7D079EB1,
  118.  0xF00F9344,0x8708A3D2,0x1E01F268,0x6906C2FE,0xF762575D,0x806567CB,
  119.  0x196C3671,0x6E6B06E7,0xFED41B76,0x89D32BE0,0x10DA7A5A,0x67DD4ACC,
  120.  0xF9B9DF6F,0x8EBEEFF9,0x17B7BE43,0x60B08ED5,0xD6D6A3E8,0xA1D1937E,
  121.  0x38D8C2C4,0x4FDFF252,0xD1BB67F1,0xA6BC5767,0x3FB506DD,0x48B2364B,
  122.  0xD80D2BDA,0xAF0A1B4C,0x36034AF6,0x41047A60,0xDF60EFC3,0xA867DF55,
  123.  0x316E8EEF,0x4669BE79,0xCB61B38C,0xBC66831A,0x256FD2A0,0x5268E236,
  124.  0xCC0C7795,0xBB0B4703,0x220216B9,0x5505262F,0xC5BA3BBE,0xB2BD0B28,
  125.  0x2BB45A92,0x5CB36A04,0xC2D7FFA7,0xB5D0CF31,0x2CD99E8B,0x5BDEAE1D,
  126.  0x9B64C2B0,0xEC63F226,0x756AA39C,0x026D930A,0x9C0906A9,0xEB0E363F,
  127.  0x72076785,0x05005713,0x95BF4A82,0xE2B87A14,0x7BB12BAE,0x0CB61B38,
  128.  0x92D28E9B,0xE5D5BE0D,0x7CDCEFB7,0x0BDBDF21,0x86D3D2D4,0xF1D4E242,
  129.  0x68DDB3F8,0x1FDA836E,0x81BE16CD,0xF6B9265B,0x6FB077E1,0x18B74777,
  130.  0x88085AE6,0xFF0F6A70,0x66063BCA,0x11010B5C,0x8F659EFF,0xF862AE69,
  131.  0x616BFFD3,0x166CCF45,0xA00AE278,0xD70DD2EE,0x4E048354,0x3903B3C2,
  132.  0xA7672661,0xD06016F7,0x4969474D,0x3E6E77DB,0xAED16A4A,0xD9D65ADC,
  133.  0x40DF0B66,0x37D83BF0,0xA9BCAE53,0xDEBB9EC5,0x47B2CF7F,0x30B5FFE9,
  134.  0xBDBDF21C,0xCABAC28A,0x53B39330,0x24B4A3A6,0xBAD03605,0xCDD70693,
  135.  0x54DE5729,0x23D967BF,0xB3667A2E,0xC4614AB8,0x5D681B02,0x2A6F2B94,
  136.  0xB40BBE37,0xC30C8EA1,0x5A05DF1B,0x2D02EF8D
  137. };
  138.  
  139. /* ---------------------------------------------------------------------- */
  140.  
  141. static const unsigned char table_one[32]=
  142. {
  143.  0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14
  144. };
  145.  
  146. static const unsigned int table_two[32]=
  147. {
  148.  0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768,1024,
  149.  1536,2048,3072,4096,6144,8192,12288,16384,24576,32768,49152
  150. };
  151.  
  152. static const unsigned int table_three[16]=
  153. {
  154.  0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767
  155. };
  156.  
  157. static const unsigned char table_four[34]=
  158. {
  159.  0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,
  160.  0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16
  161. };
  162.  
  163. /* ---------------------------------------------------------------------- */
  164.  
  165. /* Possible problems with 64 bit machines here. It kept giving warnings   */
  166. /* for people so I changed back to ~.                                     */
  167.  
  168. void crc_calc(unsigned char *memory, unsigned int length)
  169. {
  170.  register unsigned int temp;
  171.  
  172.  if(length)
  173.  {
  174.   temp = ~sum; /* was (sum ^ 4294967295) */
  175.   do
  176.   {
  177.    temp = crc_table[(*memory++ ^ temp) & 255] ^ (temp >> 8);
  178.   } while(--length);
  179.   sum = ~temp; /* was (temp ^ 4294967295) */
  180.  }
  181. }
  182.  
  183. /* ---------------------------------------------------------------------- */
  184.  
  185. /* Build a fast huffman decode table from the symbol bit lengths.         */
  186. /* There is an alternate algorithm which is faster but also more complex. */
  187.  
  188. int make_decode_table(int number_symbols, int table_size,
  189.                       unsigned char *length, unsigned short *table)
  190. {
  191.  register unsigned char bit_num = 0;
  192.  register int symbol;
  193.  unsigned int leaf; /* could be a register */
  194.  unsigned int table_mask, bit_mask, pos, fill, next_symbol, reverse;
  195.  int abort = 0;
  196.  
  197.  pos = 0; /* consistantly used as the current position in the decode table */
  198.  
  199.  bit_mask = table_mask = 1 << table_size;
  200.  
  201.  bit_mask >>= 1; /* don't do the first number */
  202.  bit_num++;
  203.  
  204.  while((!abort) && (bit_num <= table_size))
  205.  {
  206.   for(symbol = 0; symbol < number_symbols; symbol++)
  207.   {
  208.    if(length[symbol] == bit_num)
  209.    {
  210.     reverse = pos; /* reverse the order of the position's bits */
  211.     leaf = 0;
  212.     fill = table_size;
  213.     do /* reverse the position */
  214.     {
  215.      leaf = (leaf << 1) + (reverse & 1);
  216.      reverse >>= 1;
  217.     } while(--fill);
  218.     if((pos += bit_mask) > table_mask)
  219.     {
  220.      abort = 1;
  221.      break; /* we will overrun the table! abort! */
  222.     }
  223.     fill = bit_mask;
  224.     next_symbol = 1 << bit_num;
  225.     do
  226.     {
  227.      table[leaf] = symbol;
  228.      leaf += next_symbol;
  229.     } while(--fill);
  230.    }
  231.   }
  232.   bit_mask >>= 1;
  233.   bit_num++;
  234.  }
  235.  
  236.  if((!abort) && (pos != table_mask))
  237.  {
  238.   for(symbol = pos; symbol < table_mask; symbol++) /* clear the rest of the table */
  239.   {
  240.    reverse = symbol; /* reverse the order of the position's bits */
  241.    leaf = 0;
  242.    fill = table_size;
  243.    do /* reverse the position */
  244.    {
  245.     leaf = (leaf << 1) + (reverse & 1);
  246.     reverse >>= 1;
  247.    } while(--fill);
  248.    table[leaf] = 0;
  249.   }
  250.   next_symbol = table_mask >> 1;
  251.   pos <<= 16;
  252.   table_mask <<= 16;
  253.   bit_mask = 32768;
  254.  
  255.   while((!abort) && (bit_num <= 16))
  256.   {
  257.    for(symbol = 0; symbol < number_symbols; symbol++)
  258.    {
  259.     if(length[symbol] == bit_num)
  260.     {
  261.      reverse = pos >> 16; /* reverse the order of the position's bits */
  262.      leaf = 0;
  263.      fill = table_size;
  264.      do /* reverse the position */
  265.      {
  266.       leaf = (leaf << 1) + (reverse & 1);
  267.       reverse >>= 1;
  268.      } while(--fill);
  269.      for(fill = 0; fill < bit_num - table_size; fill++)
  270.      {
  271.       if(table[leaf] == 0)
  272.       {
  273.        table[(next_symbol << 1)] = 0;
  274.        table[(next_symbol << 1) + 1] = 0;
  275.        table[leaf] = next_symbol++;
  276.       }
  277.       leaf = table[leaf] << 1;
  278.       leaf += (pos >> (15 - fill)) & 1;
  279.      }
  280.      table[leaf] = symbol;
  281.      if((pos += bit_mask) > table_mask)
  282.      {
  283.       abort = 1;
  284.       break; /* we will overrun the table! abort! */
  285.      }
  286.     }
  287.    }
  288.    bit_mask >>= 1;
  289.    bit_num++;
  290.   }
  291.  }
  292.  if(pos != table_mask) abort = 1; /* the table is incomplete! */
  293.  
  294.  return(abort);
  295. }
  296.  
  297. /* ---------------------------------------------------------------------- */
  298.  
  299. /* Read and build the decrunch tables. There better be enough data in the */
  300. /* source buffer or it's stuffed. */
  301.  
  302. int read_literal_table()
  303. {
  304.  register unsigned int control;
  305.  register int shift;
  306.  unsigned int temp; /* could be a register */
  307.  unsigned int symbol, pos, count, fix, max_symbol;
  308.  int abort = 0;
  309.  
  310.  control = global_control;
  311.  shift = global_shift;
  312.  
  313.  if(shift < 0) /* fix the control word if necessary */
  314.  {
  315.   shift += 16;
  316.   control += *source++ << (8 + shift);
  317.   control += *source++ << shift;
  318.  }
  319.  
  320. /* read the decrunch method */
  321.  
  322.  decrunch_method = control & 7;
  323.  control >>= 3;
  324.  if((shift -= 3) < 0)
  325.  {
  326.   shift += 16;
  327.   control += *source++ << (8 + shift);
  328.   control += *source++ << shift;
  329.  }
  330.  
  331. /* Read and build the offset huffman table */
  332.  
  333.  if((!abort) && (decrunch_method == 3))
  334.  {
  335.   for(temp = 0; temp < 8; temp++)
  336.   {
  337.    offset_len[temp] = control & 7;
  338.    control >>= 3;
  339.    if((shift -= 3) < 0)
  340.    {
  341.     shift += 16;
  342.     control += *source++ << (8 + shift);
  343.     control += *source++ << shift;
  344.    }
  345.   }
  346.   abort = make_decode_table(8, 7, offset_len, offset_table);
  347.  }
  348.  
  349. /* read decrunch length */
  350.  
  351.  if(!abort)
  352.  {
  353.   decrunch_length = (control & 255) << 16;
  354.   control >>= 8;
  355.   if((shift -= 8) < 0)
  356.   {
  357.    shift += 16;
  358.    control += *source++ << (8 + shift);
  359.    control += *source++ << shift;
  360.   }
  361.   decrunch_length += (control & 255) << 8;
  362.   control >>= 8;
  363.   if((shift -= 8) < 0)
  364.   {
  365.    shift += 16;
  366.    control += *source++ << (8 + shift);
  367.    control += *source++ << shift;
  368.   }
  369.   decrunch_length += (control & 255);
  370.   control >>= 8;
  371.   if((shift -= 8) < 0)
  372.   {
  373.    shift += 16;
  374.    control += *source++ << (8 + shift);
  375.    control += *source++ << shift;
  376.   }
  377.  }
  378.  
  379. /* read and build the huffman literal table */
  380.  
  381.  if((!abort) && (decrunch_method != 1))
  382.  {
  383.   pos = 0;
  384.   fix = 1;
  385.   max_symbol = 256;
  386.  
  387.   do
  388.   {
  389.    for(temp = 0; temp < 20; temp++)
  390.    {
  391.     huffman20_len[temp] = control & 15;
  392.     control >>= 4;
  393.     if((shift -= 4) < 0)
  394.     {
  395.      shift += 16;
  396.      control += *source++ << (8 + shift);
  397.      control += *source++ << shift;
  398.     }
  399.    }
  400.    abort = make_decode_table(20, 6, huffman20_len, huffman20_table);
  401.  
  402.    if(abort) break; /* argh! table is corrupt! */
  403.  
  404.    do
  405.    {
  406.     if((symbol = huffman20_table[control & 63]) >= 20)
  407.     {
  408.      do /* symbol is longer than 6 bits */
  409.      {
  410.       symbol = huffman20_table[((control >> 6) & 1) + (symbol << 1)];
  411.       if(!shift--)
  412.       {
  413.        shift += 16;
  414.        control += *source++ << 24;
  415.        control += *source++ << 16;
  416.       }
  417.       control >>= 1;
  418.      } while(symbol >= 20);
  419.      temp = 6;
  420.     }
  421.     else
  422.     {
  423.      temp = huffman20_len[symbol];
  424.     }
  425.     control >>= temp;
  426.     if((shift -= temp) < 0)
  427.     {
  428.      shift += 16;
  429.      control += *source++ << (8 + shift);
  430.      control += *source++ << shift;
  431.     }
  432.     switch(symbol)
  433.     {
  434.      case 17:
  435.      case 18:
  436.      {
  437.       if(symbol == 17)
  438.       {
  439.        temp = 4;
  440.        count = 3;
  441.       }
  442.       else /* symbol == 18 */
  443.       {
  444.        temp = 6 - fix;
  445.        count = 19;
  446.       }
  447.       count += (control & table_three[temp]) + fix;
  448.       control >>= temp;
  449.       if((shift -= temp) < 0)
  450.       {
  451.        shift += 16;
  452.        control += *source++ << (8 + shift);
  453.        control += *source++ << shift;
  454.       }
  455.       while((pos < max_symbol) && (count--))
  456.        literal_len[pos++] = 0;
  457.       break;
  458.      }
  459.      case 19:
  460.      {
  461.       count = (control & 1) + 3 + fix;
  462.       if(!shift--)
  463.       {
  464.        shift += 16;
  465.        control += *source++ << 24;
  466.        control += *source++ << 16;
  467.       }
  468.       control >>= 1;
  469.       if((symbol = huffman20_table[control & 63]) >= 20)
  470.       {
  471.        do /* symbol is longer than 6 bits */
  472.        {
  473.         symbol = huffman20_table[((control >> 6) & 1) + (symbol << 1)];
  474.         if(!shift--)
  475.         {
  476.          shift += 16;
  477.          control += *source++ << 24;
  478.          control += *source++ << 16;
  479.         }
  480.         control >>= 1;
  481.        } while(symbol >= 20);
  482.        temp = 6;
  483.       }
  484.       else
  485.       {
  486.        temp = huffman20_len[symbol];
  487.       }
  488.       control >>= temp;
  489.       if((shift -= temp) < 0)
  490.       {
  491.        shift += 16;
  492.        control += *source++ << (8 + shift);
  493.        control += *source++ << shift;
  494.       }
  495.       symbol = table_four[literal_len[pos] + 17 - symbol];
  496.       while((pos < max_symbol) && (count--))
  497.        literal_len[pos++] = symbol;
  498.       break;
  499.      }
  500.      default:
  501.      {
  502.       symbol = table_four[literal_len[pos] + 17 - symbol];
  503.       literal_len[pos++] = symbol;
  504.       break;
  505.      }
  506.     }
  507.    } while(pos < max_symbol);
  508.    fix--;
  509.    max_symbol += 512;
  510.   } while(max_symbol == 768);
  511.  
  512.   if(!abort)
  513.    abort = make_decode_table(768, 12, literal_len, literal_table);
  514.  }
  515.  
  516.  global_control = control;
  517.  global_shift = shift;
  518.  
  519.  return(abort);
  520. }
  521.  
  522. /* ---------------------------------------------------------------------- */
  523.  
  524. /* Fill up the decrunch buffer. Needs lots of overrun for both destination */
  525. /* and source buffers. Most of the time is spent in this routine so it's  */
  526. /* pretty damn optimized. */
  527.  
  528. void decrunch()
  529. {
  530.  register unsigned int control;
  531.  register int shift;
  532.  unsigned int temp; /* could be a register */
  533.  unsigned int symbol, count;
  534.  unsigned char *string;
  535.  
  536.  control = global_control;
  537.  shift = global_shift;
  538.  
  539.  do
  540.  {
  541.   if((symbol = literal_table[control & 4095]) >= 768)
  542.   {
  543.    control >>= 12;
  544.    if((shift -= 12) < 0)
  545.    {
  546.     shift += 16;
  547.     control += *source++ << (8 + shift);
  548.     control += *source++ << shift;
  549.    }
  550.    do /* literal is longer than 12 bits */
  551.    {
  552.     symbol = literal_table[(control & 1) + (symbol << 1)];
  553.     if(!shift--)
  554.     {
  555.      shift += 16;
  556.      control += *source++ << 24;
  557.      control += *source++ << 16;
  558.     }
  559.     control >>= 1;
  560.    } while(symbol >= 768);
  561.   }
  562.   else
  563.   {
  564.    temp = literal_len[symbol];
  565.    control >>= temp;
  566.    if((shift -= temp) < 0)
  567.    {
  568.     shift += 16;
  569.     control += *source++ << (8 + shift);
  570.     control += *source++ << shift;
  571.    }
  572.   }
  573.   if(symbol < 256)
  574.   {
  575.    *destination++ = symbol;
  576.   }
  577.   else
  578.   {
  579.    symbol -= 256;
  580.    count = table_two[temp = symbol & 31];
  581.    temp = table_one[temp];
  582.    if((temp >= 3) && (decrunch_method == 3))
  583.    {
  584.     temp -= 3;
  585.     count += ((control & table_three[temp]) << 3);
  586.     control >>= temp;
  587.     if((shift -= temp) < 0)
  588.     {
  589.      shift += 16;
  590.      control += *source++ << (8 + shift);
  591.      control += *source++ << shift;
  592.     }
  593.     count += (temp = offset_table[control & 127]);
  594.     temp = offset_len[temp];
  595.    }
  596.    else
  597.    {
  598.     count += control & table_three[temp];
  599.     if(!count) count = last_offset;
  600.    }
  601.    control >>= temp;
  602.    if((shift -= temp) < 0)
  603.    {
  604.     shift += 16;
  605.     control += *source++ << (8 + shift);
  606.     control += *source++ << shift;
  607.    }
  608.    last_offset = count;
  609.  
  610.    count = table_two[temp = (symbol >> 5) & 15] + 3;
  611.    temp = table_one[temp];
  612.    count += (control & table_three[temp]);
  613.    control >>= temp;
  614.    if((shift -= temp) < 0)
  615.    {
  616.     shift += 16;
  617.     control += *source++ << (8 + shift);
  618.     control += *source++ << shift;
  619.    }
  620.    string = (decrunch_buffer + last_offset < destination) ?
  621.             destination - last_offset : destination + 65536 - last_offset;
  622.    do
  623.    {
  624.     *destination++ = *string++;
  625.    } while(--count);
  626.   }
  627.  } while((destination < destination_end) && (source < source_end));
  628.  
  629.  global_control = control;
  630.  global_shift = shift;
  631. }
  632.  
  633. /* ---------------------------------------------------------------------- */
  634.  
  635. /* Opens a file for writing & creates the full path if required. */
  636.  
  637. FILE *open_output(char *filename)
  638. {
  639.  unsigned int temp;
  640.  FILE *file;
  641.  
  642.  if(!(file = fopen(filename, "wb")))
  643.  {
  644. /* couldn't open the file. try and create directories */
  645.   for(temp = 0; filename[temp]; temp++)
  646.   {
  647.    if(filename[temp] == '/')
  648.    {
  649.     filename[temp] = 0;
  650.     mkdir(filename, 511); /* I don't care if it works or not */
  651.     filename[temp] = '/';
  652.    }
  653.   }
  654.   if(!(file = fopen(filename, "wb")))
  655.   {
  656.    perror("FOpen");
  657.   }
  658.  }
  659.  return(file);
  660. }
  661.  
  662. /* ---------------------------------------------------------------------- */
  663.  
  664. /* Trying to understand this function is hazardous. */
  665.  
  666. int extract_normal(FILE *in_file)
  667. {
  668.  struct filename_node *node;
  669.  FILE *out_file = 0;
  670.  unsigned char *pos;
  671.  unsigned char *temp;
  672.  unsigned int count;
  673.  int abort = 0;
  674.  
  675.  global_control = 0; /* initial control word */
  676.  global_shift = -16;
  677.  last_offset = 1;
  678.  unpack_size = 0;
  679.  decrunch_length = 0;
  680.  
  681.  for(count = 0; count < 8; count++)
  682.   offset_len[count] = 0;
  683.  for(count = 0; count < 768; count ++)
  684.   literal_len[count] = 0;
  685.  
  686.  source_end = (source = read_buffer + 16384) - 1024;
  687.  pos = destination_end = destination = decrunch_buffer + 258 + 65536;
  688.  
  689.  for(node = filename_list; (!abort) && node; node = node->next)
  690.  {
  691.   printf("Extracting \"%s\"...", node->filename);
  692.   fflush(stdout);
  693.  
  694.   out_file = open_output(node->filename);
  695.  
  696.   sum = 0; /* reset CRC */
  697.  
  698.   unpack_size = node->length;
  699.  
  700.   while(unpack_size > 0)
  701.   {
  702.  
  703.    if(pos == destination) /* time to fill the buffer? */
  704.    {
  705. /* check if we have enough data and read some if not */
  706.     if(source >= source_end) /* have we exhausted the current read buffer? */
  707.     {
  708.      temp = read_buffer;
  709.      if(count = temp - source + 16384)
  710.      {
  711.       do /* copy the remaining overrun to the start of the buffer */
  712.       {
  713.        *temp++ = *source++;
  714.       } while(--count);
  715.      }
  716.      source = read_buffer;
  717.      count = source - temp + 16384;
  718.  
  719.      if(pack_size < count) count = pack_size; /* make sure we don't read too much */
  720.  
  721.      if(fread(temp, 1, count, in_file) != count)
  722.      {
  723.       printf("\n");
  724.       if(ferror(in_file))
  725.        perror("FRead(Data)");
  726.       else
  727.        fprintf(stderr, "EOF: Data\n");
  728.       abort = 1;
  729.       break; /* fatal error */
  730.      }
  731.      pack_size -= count;
  732.  
  733.      temp += count;
  734.      if(source >= temp) break; /* argh! no more data! */
  735.     } /* if(source >= source_end) */
  736.  
  737. /* check if we need to read the tables */
  738.     if(decrunch_length <= 0)
  739.     {
  740.      if(read_literal_table()) break; /* argh! can't make huffman tables! */
  741.     }
  742.  
  743. /* unpack some data */
  744.     if(destination >= decrunch_buffer + 258 + 65536)
  745.     {
  746.      if(count = destination - decrunch_buffer - 65536)
  747.      {
  748.       temp = (destination = decrunch_buffer) + 65536;
  749.       do /* copy the overrun to the start of the buffer */
  750.       {
  751.        *destination++ = *temp++;
  752.       } while(--count);
  753.      }
  754.      pos = destination;
  755.     }
  756.     destination_end = destination + decrunch_length;
  757.     if(destination_end > decrunch_buffer + 258 + 65536)
  758.      destination_end = decrunch_buffer + 258 + 65536;
  759.     temp = destination;
  760.  
  761.     decrunch();
  762.  
  763.     decrunch_length -= (destination - temp);
  764.    }
  765.  
  766. /* calculate amount of data we can use before we need to fill the buffer again */
  767.    count = destination - pos;
  768.    if(count > unpack_size) count = unpack_size; /* take only what we need */
  769.  
  770.    crc_calc(pos, count);
  771.  
  772.    if(out_file) /* Write the data to the file */
  773.    {
  774.     if(fwrite(pos, 1, count, out_file) != count)
  775.     {
  776.      perror("FWrite"); /* argh! write error */
  777.      fclose(out_file);
  778.      out_file = 0;
  779.     }
  780.    }
  781.    unpack_size -= count;
  782.    pos += count;
  783.   }
  784.  
  785.   if(out_file)
  786.   {
  787.    fclose(out_file);
  788.    if(!abort) printf(" crc %s\n", (node->crc == sum) ? "good" : "bad");
  789.   }
  790.  } /* for */
  791.  
  792.  return(abort);
  793. }
  794.  
  795. /* ---------------------------------------------------------------------- */
  796.  
  797. /* This is less complex than extract_normal. Almost decipherable. */
  798.  
  799. int extract_store(FILE *in_file)
  800. {
  801.  struct filename_node *node;
  802.  FILE *out_file;
  803.  unsigned int count;
  804.  int abort = 0;
  805.  
  806.  for(node = filename_list; (!abort) && node; node = node->next)
  807.  {
  808.   printf("Storing \"%s\"...", node->filename);
  809.   fflush(stdout);
  810.  
  811.   out_file = open_output(node->filename);
  812.  
  813.   sum = 0; /* reset CRC */
  814.  
  815.   unpack_size = node->length;
  816.   if(unpack_size > pack_size) unpack_size = pack_size;
  817.  
  818.   while(unpack_size > 0)
  819.   {
  820.    count = (unpack_size > 16384) ? 16384 : unpack_size;
  821.  
  822.    if(fread(read_buffer, 1, count, in_file) != count)
  823.    {
  824.     printf("\n");
  825.     if(ferror(in_file))
  826.      perror("FRead(Data)");
  827.     else
  828.      fprintf(stderr, "EOF: Data\n");
  829.     abort = 1;
  830.     break; /* fatal error */
  831.    }
  832.    pack_size -= count;
  833.  
  834.    crc_calc(read_buffer, count);
  835.  
  836.    if(out_file) /* Write the data to the file */
  837.    {
  838.     if(fwrite(read_buffer, 1, count, out_file) != count)
  839.     {
  840.      perror("FWrite"); /* argh! write error */
  841.      fclose(out_file);
  842.      out_file = 0;
  843.     }
  844.    }
  845.    unpack_size -= count;
  846.   }
  847.  
  848.   if(out_file)
  849.   {
  850.    fclose(out_file);
  851.    if(!abort) printf(" crc %s\n", (node->crc == sum) ? "good" : "bad");
  852.   }
  853.  } /* for */
  854.  
  855.  return(abort);
  856. }
  857.  
  858. /* ---------------------------------------------------------------------- */
  859.  
  860. /* Easiest of the three. Just print the file(s) we didn't understand. */
  861.  
  862. int extract_unknown(FILE *in_file)
  863. {
  864.  struct filename_node *node;
  865.  int abort = 0;
  866.  
  867.  for(node = filename_list; node; node = node->next)
  868.  {
  869.   printf("Unknown \"%s\"\n", node->filename);
  870.  }
  871.  
  872.  return(abort);
  873. }
  874.  
  875. /* ---------------------------------------------------------------------- */
  876.  
  877. /* Read the archive and build a linked list of names. Merged files is     */
  878. /* always assumed. Will fail if there is no memory for a node. Sigh.      */
  879.  
  880. int extract_archive(FILE *in_file)
  881. {
  882.  unsigned int temp;
  883.  struct filename_node **filename_next;
  884.  struct filename_node *node;
  885.  struct filename_node *temp_node;
  886.  int actual;
  887.  int abort;
  888.  int result = 1; /* assume an error */
  889.  
  890.  filename_list = 0; /* clear the list */
  891.  filename_next = &filename_list;
  892.  
  893.  do
  894.  {
  895.   abort = 1; /* assume an error */
  896.   actual = fread(archive_header, 1, 31, in_file);
  897.   if(!ferror(in_file))
  898.   {
  899.    if(actual) /* 0 is normal and means EOF */
  900.    {
  901.     if(actual == 31)
  902.     {
  903.      sum = 0; /* reset CRC */
  904.      crc = (archive_header[29] << 24) + (archive_header[28] << 16) + (archive_header[27] << 8) + archive_header[26]; /* header crc */
  905.      archive_header[29] = 0; /* Must set the field to 0 before calculating the crc */
  906.      archive_header[28] = 0;
  907.      archive_header[27] = 0;
  908.      archive_header[26] = 0;
  909.      crc_calc(archive_header, 31);
  910.      temp = archive_header[30]; /* filename length */
  911.      actual = fread(header_filename, 1, temp, in_file);
  912.      if(!ferror(in_file))
  913.      {
  914.       if(actual == temp)
  915.       {
  916.        header_filename[temp] = 0;
  917.        crc_calc(header_filename, temp);
  918.        temp = archive_header[14]; /* comment length */
  919.        actual = fread(header_comment, 1, temp, in_file);
  920.        if(!ferror(in_file))
  921.        {
  922.         if(actual == temp)
  923.         {
  924.          header_comment[temp] = 0;
  925.          crc_calc(header_comment, temp);
  926.          if(sum == crc)
  927.          {
  928.           unpack_size = (archive_header[5] << 24) + (archive_header[4] << 16) + (archive_header[3] << 8) + archive_header[2]; /* unpack size */
  929.           pack_size = (archive_header[9] << 24) + (archive_header[8] << 16) + (archive_header[7] << 8) + archive_header[6]; /* packed size */
  930.           pack_mode = archive_header[11]; /* pack mode */
  931.           crc = (archive_header[25] << 24) + (archive_header[24] << 16) + (archive_header[23] << 8) + archive_header[22]; /* data crc */
  932.  
  933.           if(node = (struct filename_node *)malloc(sizeof(struct filename_node))) /* allocate a filename node */
  934.           {
  935.            *filename_next = node; /* add this node to the list */
  936.            filename_next = &(node->next);
  937.            node->next = 0;
  938.            node->length = unpack_size;
  939.            node->crc = crc;
  940.            for(temp = 0; node->filename[temp] = header_filename[temp]; temp++);
  941.  
  942.            if(pack_size)
  943.            {
  944.             switch(pack_mode)
  945.             {
  946.              case 0: /* store */
  947.              {
  948.               abort = extract_store(in_file);
  949.               break;
  950.              }
  951.              case 2: /* normal */
  952.              {
  953.               abort = extract_normal(in_file);
  954.               break;
  955.              }
  956.              default: /* unknown */
  957.              {
  958.               abort = extract_unknown(in_file);
  959.               break;
  960.              }
  961.             }
  962.             if(abort) break; /* a read error occured */
  963.  
  964.             temp_node = filename_list; /* free the list now */
  965.             while(node = temp_node)
  966.             {
  967.              temp_node = node->next;
  968.              free(node);
  969.             }
  970.             filename_list = 0; /* clear the list */
  971.             filename_next = &filename_list;
  972.  
  973.             if(fseek(in_file, pack_size, SEEK_CUR))
  974.             {
  975.              perror("FSeek(Data)");
  976.              break;
  977.             }
  978.            }
  979.            else
  980.             abort = 0; /* continue */
  981.           }
  982.           else
  983.            fprintf(stderr, "MAlloc(Filename_node)\n");
  984.          }
  985.          else
  986.           fprintf(stderr, "CRC: Archive_Header\n");
  987.         }
  988.         else
  989.          fprintf(stderr, "EOF: Header_Comment\n");
  990.        }
  991.        else
  992.         perror("FRead(Header_Comment)");
  993.       }
  994.       else
  995.        fprintf(stderr, "EOF: Header_Filename\n");
  996.      }
  997.      else
  998.       perror("FRead(Header_Filename)");
  999.     }
  1000.     else
  1001.      fprintf(stderr, "EOF: Archive_Header\n");
  1002.    }
  1003.    else
  1004.    {
  1005.     result = 0; /* normal termination */
  1006.    }
  1007.   }
  1008.   else
  1009.    perror("FRead(Archive_Header)");
  1010.  } while(!abort);
  1011.  
  1012. /* free the filename list in case an error occured */
  1013.  temp_node = filename_list;
  1014.  while(node = temp_node)
  1015.  {
  1016.   temp_node = node->next;
  1017.   free(node);
  1018.  }
  1019.  
  1020.  return(result);
  1021. }
  1022.  
  1023. /* ---------------------------------------------------------------------- */
  1024.  
  1025. /* List the contents of an archive in a nice formatted kinda way.         */
  1026.  
  1027. int view_archive(FILE *in_file)
  1028. {
  1029.  unsigned int temp;
  1030.  unsigned int total_pack = 0;
  1031.  unsigned int total_unpack = 0;
  1032.  unsigned int total_files = 0;
  1033.  unsigned int merge_size = 0;
  1034.  int actual;
  1035.  int abort;
  1036.  int result = 1; /* assume an error */
  1037.  
  1038.  printf("Unpacked   Packed Time     Date        Attrib   Name\n");
  1039.  printf("-------- -------- -------- ----------- -------- ----\n");
  1040.  
  1041.  do
  1042.  {
  1043.   abort = 1; /* assume an error */
  1044.   actual = fread(archive_header, 1, 31, in_file);
  1045.   if(!ferror(in_file))
  1046.   {
  1047.    if(actual) /* 0 is normal and means EOF */
  1048.    {
  1049.     if(actual == 31)
  1050.     {
  1051.      sum = 0; /* reset CRC */
  1052.      crc = (archive_header[29] << 24) + (archive_header[28] << 16) + (archive_header[27] << 8) + archive_header[26];
  1053.      archive_header[29] = 0; /* Must set the field to 0 before calculating the crc */
  1054.      archive_header[28] = 0;
  1055.      archive_header[27] = 0;
  1056.      archive_header[26] = 0;
  1057.      crc_calc(archive_header, 31);
  1058.      temp = archive_header[30]; /* filename length */
  1059.      actual = fread(header_filename, 1, temp, in_file);
  1060.      if(!ferror(in_file))
  1061.      {
  1062.       if(actual == temp)
  1063.       {
  1064.        header_filename[temp] = 0;
  1065.        crc_calc(header_filename, temp);
  1066.        temp = archive_header[14]; /* comment length */
  1067.        actual = fread(header_comment, 1, temp, in_file);
  1068.        if(!ferror(in_file))
  1069.        {
  1070.         if(actual == temp)
  1071.         {
  1072.          header_comment[temp] = 0;
  1073.          crc_calc(header_comment, temp);
  1074.          if(sum == crc)
  1075.          {
  1076.           attributes = archive_header[0]; /* file protection modes */
  1077.           unpack_size = (archive_header[5] << 24) + (archive_header[4] << 16) + (archive_header[3] << 8) + archive_header[2]; /* unpack size */
  1078.           pack_size = (archive_header[9] << 24) + (archive_header[8] << 16) + (archive_header[7] << 8) + archive_header[6]; /* packed size */
  1079.           temp = (archive_header[18] << 24) + (archive_header[19] << 16) + (archive_header[20] << 8) + archive_header[21]; /* date */
  1080.           year = ((temp >> 17) & 63) + 1970;
  1081.           month = (temp >> 23) & 15;
  1082.           day = (temp >> 27) & 31;
  1083.           hour = (temp >> 12) & 31;
  1084.           minute = (temp >> 6) & 63;
  1085.           second = temp & 63;
  1086.  
  1087.           total_pack += pack_size;
  1088.           total_unpack += unpack_size;
  1089.           total_files++;
  1090.           merge_size += unpack_size;
  1091.  
  1092.           printf("%8ld ", unpack_size);
  1093.           if(archive_header[12] & 1)
  1094.            printf("     n/a ");
  1095.           else
  1096.            printf("%8ld ", pack_size);
  1097.           printf("%02ld:%02ld:%02ld ", hour, minute, second);
  1098.           printf("%2ld-%s-%4ld ", day, month_str[month], year);
  1099.           printf("%c%c%c%c%c%c%c%c ",
  1100.                  (attributes & 32) ? 'h' : '-',
  1101.                  (attributes & 64) ? 's' : '-',
  1102.                  (attributes & 128) ? 'p' : '-',
  1103.                  (attributes & 16) ? 'a' : '-',
  1104.                  (attributes & 1) ? 'r' : '-',
  1105.                  (attributes & 2) ? 'w' : '-',
  1106.                  (attributes & 8) ? 'e' : '-',
  1107.                  (attributes & 4) ? 'd' : '-');
  1108.           printf("\"%s\"\n", header_filename);
  1109.           if(header_comment[0])
  1110.            printf(": \"%s\"\n", header_comment);
  1111.           if((archive_header[12] & 1) && pack_size)
  1112.           {
  1113.            printf("%8ld %8ld Merged\n", merge_size, pack_size);
  1114.           }
  1115.  
  1116.           if(pack_size) /* seek past the packed data */
  1117.           {
  1118.            merge_size = 0;
  1119.            if(!fseek(in_file, pack_size, SEEK_CUR))
  1120.            {
  1121.             abort = 0; /* continue */
  1122.            }
  1123.            else
  1124.             perror("FSeek()");
  1125.           }
  1126.           else
  1127.            abort = 0; /* continue */
  1128.          }
  1129.          else
  1130.           fprintf(stderr, "CRC: Archive_Header\n");
  1131.         }
  1132.         else
  1133.          fprintf(stderr, "EOF: Header_Comment\n");
  1134.        }
  1135.        else
  1136.         perror("FRead(Header_Comment)");
  1137.       }
  1138.       else
  1139.        fprintf(stderr, "EOF: Header_Filename\n");
  1140.      }
  1141.      else
  1142.       perror("FRead(Header_Filename)");
  1143.     }
  1144.     else
  1145.      fprintf(stderr, "EOF: Archive_Header\n");
  1146.    }
  1147.    else
  1148.    {
  1149.     printf("-------- -------- -------- ----------- -------- ----\n");
  1150.     printf("%8ld %8ld ", total_unpack, total_pack);
  1151.     printf("%ld file%s\n", total_files, ((total_files == 1) ? "" : "s"));
  1152.  
  1153.     result = 0; /* normal termination */
  1154.    }
  1155.   }
  1156.   else
  1157.    perror("FRead(Archive_Header)");
  1158.  } while(!abort);
  1159.  
  1160.  return(result);
  1161. }
  1162.  
  1163. /* ---------------------------------------------------------------------- */
  1164.  
  1165. /* Process a single archive. */
  1166.  
  1167. int process_archive(char *filename)
  1168. {
  1169.  int result = 1; /* assume an error */
  1170.  FILE *in_file;
  1171.  int actual;
  1172.  
  1173.  if(in_file = fopen(filename,"rb"))
  1174.  {
  1175.   actual = fread(info_header, 1, 10, in_file);
  1176.   if(!ferror(in_file))
  1177.   {
  1178.    if(actual == 10)
  1179.    {
  1180.     if((info_header[0] == 76) && (info_header[1] == 90) && (info_header[2] == 88)) /* LZX */
  1181.     {
  1182.      switch(mode)
  1183.      {
  1184.       case 1: /* extract archive */
  1185.       {
  1186.        result = extract_archive(in_file);
  1187.        break;
  1188.       }
  1189.       case 2: /* view archive */
  1190.       {
  1191.        result = view_archive(in_file);
  1192.        break;
  1193.       }
  1194.      }
  1195.     }
  1196.     else
  1197.      fprintf(stderr, "Info_Header: Bad ID\n");
  1198.    }
  1199.    else
  1200.     fprintf(stderr, "EOF: Info_Header\n");
  1201.   }
  1202.   else
  1203.    perror("FRead(Info_Header)");
  1204.   fclose(in_file);
  1205.  }
  1206.  else
  1207.   perror("FOpen(Archive)");
  1208.  return(result);
  1209. }
  1210.  
  1211. /* ---------------------------------------------------------------------- */
  1212.  
  1213. /* Handle options & multiple filenames. */
  1214.  
  1215. int main(int argc, char **argv)
  1216. {
  1217.  int result = 0;
  1218.  int option;
  1219.  extern int optind;
  1220.  
  1221.  mode = 1; /* default mode is extract */
  1222.  while ((option = getopt(argc, argv, "vx")) != EOF)
  1223.  {
  1224.   switch(option)
  1225.   {
  1226.    case 'v': /* (v)iew archive */
  1227.    {
  1228.     mode = 2;
  1229.     break;
  1230.    }
  1231.    case 'x': /* e(x)tract archive */
  1232.    {
  1233.     mode = 1;
  1234.     break;
  1235.    }
  1236.    case '?': /* unknown option */
  1237.    {
  1238.     result = 1;
  1239.     break;
  1240.    }
  1241.   }
  1242.  }
  1243.  if(optind >= argc) result = 1; /* gotta have a filename */
  1244.  
  1245.  if(!result)
  1246.  {
  1247.   if((argc - optind) > 1)
  1248.   {
  1249.    for(; optind < argc; optind++)
  1250.    {
  1251.     printf("\nArchive \"%s\"...\n\n", argv[optind]);
  1252.     process_archive(argv[optind]);
  1253.    }
  1254.    result = 0; /* Can't give a reliable result for multiple archives */
  1255.   }
  1256.   else
  1257.   {
  1258.    result = process_archive(argv[optind]); /* do a single archive */
  1259.   }
  1260.  }
  1261.  else
  1262.  {
  1263.   fprintf(stderr, "Usage: unlzx [-v][-x] archive(s)\n");
  1264.   fprintf(stderr, "\t-v : list archive(s)\n");
  1265.   fprintf(stderr, "\t-x : extract (default)\n");
  1266.   result = 2;
  1267.  }
  1268.  
  1269.  return(result);
  1270. }
  1271.  
  1272. /* ---------------------------------------------------------------------- */
  1273.  
  1274. /* Some info for the reader only. This is unused by the program and can   */
  1275. /* safely be deleted.                                                     */
  1276.  
  1277. #define INFO_DAMAGE_PROTECT 1
  1278. #define INFO_FLAG_LOCKED 2
  1279.  
  1280. /* STRUCTURE Info_Header
  1281. {
  1282.   UBYTE ID[3]; 0 - "LZX"
  1283.   UBYTE flags; 3 - INFO_FLAG_#?
  1284.   UBYTE[6]; 4
  1285. } */ /* SIZE = 10 */
  1286.  
  1287. #define HDR_FLAG_MERGED 1
  1288.  
  1289. #define HDR_PROT_READ    1
  1290. #define HDR_PROT_WRITE   2
  1291. #define HDR_PROT_DELETE  4
  1292. #define HDR_PROT_EXECUTE 8
  1293. #define HDR_PROT_ARCHIVE 16
  1294. #define HDR_PROT_HOLD    32
  1295. #define HDR_PROT_SCRIPT  64
  1296. #define HDR_PROT_PURE    128
  1297.  
  1298. #define HDR_TYPE_MSDOS   0
  1299. #define HDR_TYPE_WINDOWS 1
  1300. #define HDR_TYPE_OS2     2
  1301. #define HDR_TYPE_AMIGA   10
  1302. #define HDR_TYPE_UNIX    20
  1303.  
  1304. #define HDR_PACK_STORE    0
  1305. #define HDR_PACK_NORMAL   2
  1306. #define HDR_PACK_EOF      32
  1307.  
  1308. /* STRUCTURE Archive_Header
  1309. {
  1310.   UBYTE attributes; 0 - HDR_PROT_#?
  1311.   UBYTE; 1
  1312.   ULONG unpacked_length; 2 - FUCKED UP LITTLE ENDIAN SHIT
  1313.   ULONG packed_length; 6 - FUCKED UP LITTLE ENDIAN SHIT
  1314.   UBYTE machine_type; 10 - HDR_TYPE_#?
  1315.   UBYTE pack_mode; 11 - HDR_PACK_#?
  1316.   UBYTE flags; 12 - HDR_FLAG_#?
  1317.   UBYTE; 13
  1318.   UBYTE len_comment; 14 - comment length [0,79]
  1319.   UBYTE extract_ver; 15 - version needed to extract
  1320.   UBYTE; 16
  1321.   UBYTE; 17
  1322.   ULONG date; 18 - Packed_Date
  1323.   ULONG data_crc; 22 - FUCKED UP LITTLE ENDIAN SHIT
  1324.   ULONG header_crc; 26 - FUCKED UP LITTLE ENDIAN SHIT
  1325.   UBYTE filename_len; 30 - filename length
  1326. } */ /* SIZE = 31 */
  1327.  
  1328. #define DATE_SHIFT_YEAR   17
  1329. #define DATE_SHIFT_MONTH  23
  1330. #define DATE_SHIFT_DAY    27
  1331. #define DATE_SHIFT_HOUR   12
  1332. #define DATE_SHIFT_MINUTE 6
  1333. #define DATE_SHIFT_SECOND 0
  1334. #define DATE_MASK_YEAR    0x007E0000
  1335. #define DATE_MASK_MONTH   0x07800000
  1336. #define DATE_MASK_DAY     0xF8000000
  1337. #define DATE_MASK_HOUR    0x0001F000
  1338. #define DATE_MASK_MINUTE  0x00000FC0
  1339. #define DATE_MASK_SECOND  0x0000003F
  1340.  
  1341. /* STRUCTURE DATE_Unpacked
  1342. {
  1343.   UBYTE year; 80 - Year 0=1970 1=1971 63=2033
  1344.   UBYTE month; 81 - 0=january 1=february .. 11=december
  1345.   UBYTE day; 82
  1346.   UBYTE hour; 83
  1347.   UBYTE minute; 84
  1348.   UBYTE second; 85
  1349. } */ /* SIZE = 6 */
  1350.  
  1351. /* STRUCTURE DATE_Packed
  1352. {
  1353.   UBYTE packed[4]; bit 0 is MSB, 31 is LSB
  1354. ; bit # 0-4=Day 5-8=Month 9-14=Year 15-19=Hour 20-25=Minute 26-31=Second
  1355. } */ /* SIZE = 4 */
  1356.